//
//  ProgramFunction.cpp
//  ConstructGccfg2.0
//
//  Created by Bryce Holton on 12/8/12.
//  Copyright (c) 2012 Bryce Holton. All rights reserved.
//

#include "ProgramFunction.h"
#include <set>
#include <map>
#include "LoopBlock.h"
#include "Edge.h"

ProgramFunction::ProgramFunction()
{
    cfg = NULL;
}
ProgramFunction::~ProgramFunction()
{
    delete cfg;
    for (unsigned int i = 0; i < loops.size(); i++)
    {
        delete loops[i];
    }
    loops.clear();
}
void ProgramFunction::SeparateLoopBlocksFromFunctionBlocks()
{
    SeperateBlockSets();
    InsertLoopPlaceHolders();
    SeverBlockConnections();
    CleanUpBlockLists(); //Needs to be completed.
}
void ProgramFunction::SeperateBlockSets()
{
    for (unsigned int i = 0; i < loops.size(); i++)
    {
        set<BasicBlock *> loopSet = loops[i]->GetBlockSet();
        cfg->RemoveBlocksNotInThisSet(loopSet);
        
        for (unsigned int j = 0; j < loops.size(); j++)
        {
            if (i < j)
            {
                set<BasicBlock *> loopSet2 = loops[j]->GetBlockSet();
                loops[i]->RemoveBlocksNotInThisSet(loopSet2);
            }
        }
    }
}
void ProgramFunction::InsertLoopPlaceHolders()
{
    for (unsigned int i = 0; i < loops.size(); i++)
    {        
        cfg->FindLoopsInBlockSet(*loops[i]);
        for (unsigned int j = 0; j < loops.size(); j++)
        {
            if (i < j)
            {                
                loops[i]->FindLoopsInBlockSet(*loops[j]);
            }
        }
    }
}
void ProgramFunction::SeverBlockConnections()
{
    for (unsigned int i = 0; i < loops.size(); i++)
    {
        loops[i]->SeverChildrenNotInThisLoop();
    }
}
void ProgramFunction::CleanUpBlockLists()
{
    cfg->CleanUpBlocks();
    for (unsigned int i = 0; i < loops.size(); i++)
    {
        loops[i]->CleanUpBlocks();
    }
}
void ProgramFunction::SetCfg(ControlFlowGraph &cfg)
{
    this->cfg = &cfg;
}
void ProgramFunction::SetLoop(ControlFlowGraphLoop &loop)
{
    loops.push_back(&loop);
}
void ProgramFunction::SetSize(int s)
{
    size = s;
}
ControlFlowGraph *ProgramFunction::GetCfg()
{
    return cfg;
}
vector<ControlFlowGraphLoop *> ProgramFunction::GetLoops()
{
    return loops;
}
int ProgramFunction::GetSize()
{
    return size;
}
